// //Import Box2D constructors
var b2Vec2 = Box2D.Common.Math.b2Vec2;
var b2BodyDef = Box2D.Dynamics.b2BodyDef;
var b2Body = Box2D.Dynamics.b2Body;
var b2_staticBody = Box2D.Dynamics.b2Body.b2_staticBody;
var b2_kinematicBody = Box2D.Dynamics.b2Body.b2_kinematicBody;
var b2_dynamicBody = Box2D.Dynamics.b2Body.b2_dynamicBody;
var b2FixtureDef = Box2D.Dynamics.b2FixtureDef;
var b2Fixture = Box2D.Dynamics.b2Fixture;
var b2World = Box2D.Dynamics.b2World;
var b2MassData = Box2D.Collision.Shapes.b2MassData;
var b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape;
var b2CircleShape = Box2D.Collision.Shapes.b2CircleShape;
var b2DebugDraw = Box2D.Dynamics.b2DebugDraw;
var b2Transform = Box2D.Common.Math.b2Transform;
var b2Mat22 = Box2D.Common.Math.b2Mat22;
var b2AABB = Box2D.Collision.b2AABB;
var b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef;
var b2PrismaticJointDef = Box2D.Dynamics.Joints.b2PrismaticJointDef;
var b2WeldJointDef = Box2D.Dynamics.Joints.b2WeldJointDef;

var world;
var level = 1;

// DOM elements
var canvas = document.getElementById("canvas");
var canvas_width = canvas.width;
var canvas_height = canvas.height;
var context = canvas.getContext("2d");
var gravityButton = document.getElementById("gravityButton");
var gravityText = document.getElementById("gravityText");
var nextLevelButton = document.getElementById("nextLevel");
var restartLevelButton = document.getElementById("restartLevel");
var levelText = document.getElementById("levelText");
var levelSpec = document.getElementById("docInfo");

// Graphics Constants
var drawScale = 30.0;
var mouseClicked = false;
var mousePressed = false;
var goal = new Image();
var winningArea = new b2AABB;
var winningLocX = 260;
var winningLocY = 25;
var won = false;
var gameOver = false;
var mouseX;
var mouseY;
var selectedBody;
var fixDef;
var bodyDef;
var platformSpeed1;
var platformSpeed2;
var platformSpeed3;

// Level Documentation
var levelDoc = {
	1: "Level I -- Get the egg to the bunny. Pass through the shaded area to decorate your egg.",
	2: "Level II -- Get the egg to the bunny.",
	3: "Level III -- Get the egg to the bunny. You can use the catching platforms to move left/right.",
	4: "Level IV -- Get the egg to the bunny. Use the moving platforms to move left/right.",
	5: "Level V -- Overcome the obstacles and get the egg to the bunny!",
	6: "Level VI -- Get the egg to the bunny! Be mindful of the lightning-platforms (they can destroy " +
					"your eggs!)",
	7: "Level VII -- Get the egg to the bunny. Each of the balls will aggressively repel the egg.",
	8: "Level VIII -- Get the egg to the bunny. The blue quadrilaterals will apply a " +
					"leftwards or rightwards force on the egg.",
	9: "Level IX -- Get an egg to the bunny. Be wary of the falling squares! They will crack " +
					"your egg! You only have a random limited number of eggs!",
	10: "Level X -- Get the egg to the bunny! Each of the balls will apply a random force to the " +
					"egg. The walls on the side always apply inwards forces.",
	11: "GAME OVER"

};

// Physics Constants
var gravityDown = new b2Vec2(0, 8);
var down = true;


function init() {
	document.getElementById('splash').style.display = 'block'; 
  	setTimeout(function(){ SplashBeGone(); }, 5000000); 
	won = false;
	gameOver = false;
	down = true;
	world = new b2World(gravityDown, true);
	fixDef = new b2FixtureDef;
	fixDef.density = 1.0;
	fixDef.friction = 0.5;
	fixDef.restitution = 0.4;

	bodyDef = new b2BodyDef;

	// create bunny image
	goal.src = "bunny60x60.png";
	winningArea.lowerBound = new b2Vec2(9, ptm(winningLocY-30));
	winningArea.upperBound = new b2Vec2(11, ptm(winningLocY+30));
	console.log(winningArea);

	//create grounds
	//floor
	bodyDef.type = b2Body.b2_staticBody;
	bodyDef.position.x = ptm(canvas_width/2);
	bodyDef.position.y = ptm(canvas_height);
	bodyDef.userData="ground";
	fixDef.shape = new b2PolygonShape;
	fixDef.shape.SetAsBox(ptm(canvas_width), 0.5);
	world.CreateBody(bodyDef).CreateFixture(fixDef);
	//ceiling
	bodyDef.type = b2Body.b2_staticBody;
	bodyDef.position.x = ptm(canvas_width/2);
	bodyDef.position.y = ptm(0);
	bodyDef.type = b2_staticBody;
	bodyDef.userData="ground";
	fixDef.shape = new b2PolygonShape;
	fixDef.shape.SetAsBox(ptm(canvas_width), 0.5);
	world.CreateBody(bodyDef).CreateFixture(fixDef);
	//left side
	bodyDef.type = b2Body.b2_staticBody;
	bodyDef.position.x = 0;
	bodyDef.position.y = ptm(canvas_width/2);
	bodyDef.type = b2_staticBody;
	bodyDef.userData="ground";
	fixDef.shape = new b2PolygonShape;
	fixDef.shape.SetAsBox(0.5, ptm(canvas_height));
	world.CreateBody(bodyDef).CreateFixture(fixDef);
	//right side
	bodyDef.type = b2Body.b2_staticBody;
	bodyDef.position.x = ptm(canvas_width);
	bodyDef.position.y = ptm(canvas_width/2);
	bodyDef.type = b2_staticBody;
	bodyDef.userData="ground";
	fixDef.shape = new b2PolygonShape;
	fixDef.shape.SetAsBox(0.5, ptm(canvas_height));
	world.CreateBody(bodyDef).CreateFixture(fixDef);

	loadLevel(level);
	updateLevelInfo(level);

	// Create collision listener
	var listener = new Box2D.Dynamics.b2ContactListener;
	listener.BeginContact = function(contact) {
		var cBody = contact.GetFixtureA().GetBody().GetUserData();
		if (cBody.substr(0,3)=="dec") {
			console.log(cBody.substr(3));
			console.log("decoration!");
		} else if (cBody == "egg") {
			var cEgg = contact.GetFixtureA().GetBody();
			var cVel = cEgg.GetLinearVelocity();
			if (contact.m_nodeA.other.m_userData=="bouncerLEFT") {
				cEgg.m_linearVelocity.x = cVel.x-Math.random()*2;
			//cEgg.m_linearVelocity.y = -(cVel.y+Math.random());
			} else if (contact.m_nodeA.other.m_userData=="bouncerRIGHT") {
				cEgg.m_linearVelocity.x = cVel.x+Math.random()*2;
			} else if (contact.m_nodeA.other.m_userData=="bouncerDOWN") {

				cEgg.m_linearVelocity.y = -(Math.abs(cVel.y+Math.random()*2));
			}
		} else if (cBody == "LEFTSHOOTER") {
			//var force = velChange/15.5;
			for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
				if (bb.GetUserData()!=null) {
					if (bb.GetUserData().substr(0,3)=="egg") {
						bb.ApplyForce(new b2Vec2(-2, 0), bb.GetWorldCenter());
					}
				}
			}
		} else if (cBody == "RIGHTSHOOTER") {
			for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
				if (bb.GetUserData()!=null) {
					if (bb.GetUserData().substr(0,3)=="egg") {
						bb.ApplyForce(new b2Vec2(2, 0), bb.GetWorldCenter());
					}
				}
			}
		} else if (cBody == "blastr") {
			if (contact.m_nodeA==null) { }
			else if (contact.m_nodeA.other==null) { }
			else if (contact.m_nodeA.other.m_userData==null) { }
			else if (contact.m_nodeA.other.m_userData.substr(0,3)=="egg") {
				var nextEggNumber;
				for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
					if (bb.GetUserData()==null) { } 
					else if (bb.GetUserData()==contact.m_nodeA.other.m_userData) {
						nextEggNumber = contact.m_nodeA.other.m_userData.substr(3);
						nextEggNumber = parseInt(nextEggNumber)+1;
						killEgg(contact.m_nodeA.other.m_userData.substr(3));
					}
				}
				for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
					if (bb.GetUserData()!=null) {
						if (bb.GetUserData() == ("egg"+nextEggNumber)) {
							bb.SetActive(true);
						}
					}
				}
			}
		} else if (cBody == "forcer") {
			for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
				if (bb.GetUserData()!=null) {
					if (bb.GetUserData().substr(0,3)=="egg") {
						bb.ApplyForce(new b2Vec2(Math.random()*5, Math.random()*5), bb.GetWorldCenter());
					}
				}
			}
		}
	}
	world.SetContactListener(listener);

	//setup debug draw
	var debugDraw = new b2DebugDraw();
	debugDraw.SetSprite(canvas.getContext("2d"));
	debugDraw.SetDrawScale(drawScale);
	debugDraw.SetFillAlpha(0.3);
	debugDraw.SetLineThickness(1.0);
	debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
	world.SetDebugDraw(debugDraw);

	window.setInterval(update, 1000 / 60);
};


// Creates objects specific to each level.
function loadLevel(numLevel) {
	switch(numLevel) {
		case 1:
			//create obstacles
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.3);
			bodyDef.position.Set(5,15);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,3);
			bodyDef.position.Set(13,12);
			bodyDef.userData="joint";
			bodyDef.type = b2_dynamicBody;
			var a = world.CreateBody(bodyDef);
			a.CreateFixture(fixDef);
			var jointDef = new b2RevoluteJointDef;
			jointDef.Initialize(world.GetGroundBody(), a, new b2Vec2(13, 12));
			jointDef.maxMotorTorque = 5.0;
			jointDef.motorSpeed = 3;
			jointDef.enableMotor = true;
			world.CreateJoint(jointDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.3);
			bodyDef.position.Set(5,10);
			bodyDef.type = b2_staticBody;
			bodyDef.userData="wall";
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// create decoration areas
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,2);
			bodyDef.position.Set(5,12.5);
			bodyDef.type = b2_staticBody;
			bodyDef.userData="decBLUE";
			world.CreateBody(bodyDef).CreateFixture(fixDef).SetSensor(true);
			fixDef.shape.SetAsBox(1,1);
			bodyDef.position.Set(15,8);
			bodyDef.userData="decDOT";
			world.CreateBody(bodyDef).CreateFixture(fixDef).SetSensor(true);

			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2);
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			break;

			case 2:
			//create obstacles
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.3);
			bodyDef.position.Set(8,20);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetPositionAndAngle(temp.GetWorldCenter(), rads(-50));
			temp.CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,3.5);
			bodyDef.position.Set(13,12);
			bodyDef.userData="joint";
			bodyDef.type = b2_dynamicBody;
			var a = world.CreateBody(bodyDef);
			a.CreateFixture(fixDef);
			var jointDef = new b2RevoluteJointDef;
			jointDef.Initialize(world.GetGroundBody(), a, new b2Vec2(13, 12));
			jointDef.maxMotorTorque = 5.0;
			jointDef.motorSpeed = 3;
			jointDef.enableMotor = true;
			world.CreateJoint(jointDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.3);
			bodyDef.position.Set(5,10);
			bodyDef.type = b2_staticBody;
			bodyDef.userData="wall";
			temp = world.CreateBody(bodyDef);
			temp.SetPositionAndAngle(temp.GetWorldCenter(), rads(-50));
			temp.CreateFixture(fixDef);

			// wall around bunny
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.1,2);
			bodyDef.position.Set(7.5,2.5);
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.1,2);
			bodyDef.position.Set(12,2.5);
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2);
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			break;

			case 3:
			//create obstacles
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(8,0.3);
			bodyDef.position.Set(8.5,15);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(2.5,19);
			bodyDef.userData="platform1";
			platformSpeed1 = 2;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.5, new b2Vec2(-1.9, -0.8), 0);
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.5, new b2Vec2(1.9, -0.8), 0);
			temp.CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.3);
			bodyDef.position.Set(4,8);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.3);
			bodyDef.position.Set(16,8);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(17.5,13);
			bodyDef.userData="platform2";
			platformSpeed2 = 5;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.5, new b2Vec2(-1.9, -0.8), 0);
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.5, new b2Vec2(1.9, -0.8), 0);
			temp.CreateFixture(fixDef);


			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2);
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			break;

			case 4:
			//create obstacles
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,5);
			bodyDef.position.Set(2,21.2);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(7,0.3);
			bodyDef.position.Set(8.7,15.9);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,3);
			bodyDef.position.Set(10,23.1);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,3);
			bodyDef.position.Set(16,18.6);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			//mover
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(4.3,16.5);
			bodyDef.userData="platform1";
			platformSpeed1 = 2;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
			temp.CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(1,0.3);
			bodyDef.position.Set(11.3,25.9);
			bodyDef.userData="platform2";
			platformSpeed2 = 3;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed2, 0));
			temp.CreateFixture(fixDef);

			//moving platform
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(12.5,10);
			bodyDef.userData="platform3";
			platformSpeed3 = 4;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed3, 0));
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.5, new b2Vec2(-1.9, -0.8), 0);
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.5, new b2Vec2(1.9, -0.8), 0);
			temp.CreateFixture(fixDef);

			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2 - 150);
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			break;

			case 5:
			//mover

			//small obstaces
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(1,0.1);
			bodyDef.position.Set(4.3,16.5);
			bodyDef.userData="smallPlatform";
			platformSpeed1 = 5;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
			temp.CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(1,0.1);
			bodyDef.position.Set(8,5);
			bodyDef.userData="smallPlatform";
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(-platformSpeed1, 0));
			temp.CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(1,0.1);
			bodyDef.position.Set(9,23);
			bodyDef.userData="smallPlatform";
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
			temp.CreateFixture(fixDef);

			// big obstacles
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.1);
			bodyDef.position.Set(11.3,20);
			bodyDef.userData="bigPlatform";
			platformSpeed2 = 2;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(-platformSpeed2, 0));
			temp.CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.1);
			bodyDef.position.Set(4,14);
			bodyDef.userData="bigPlatform";
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed2, 0));
			temp.CreateFixture(fixDef);

			//moving platforms that catch
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,0.2);
			bodyDef.position.Set(3,12);
			bodyDef.userData="catchPlatform";
			platformSpeed3 = 1;
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed3, 0));
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.4, new b2Vec2(-1.9, -0.6), 0);
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.4, new b2Vec2(1.9, -0.6), 0);
			temp.CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,0.2);
			bodyDef.position.Set(17,8);
			bodyDef.userData="catchPlatform";
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(platformSpeed3, 0));
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.4, new b2Vec2(-1.9, 0.6), 0);
			temp.CreateFixture(fixDef);
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsOrientedBox(0.1,0.4, new b2Vec2(1.9, 0.6), 0);
			temp.CreateFixture(fixDef);

			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2+100);
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg1";
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			break;

			// level 6
			case 6:

			// create net at top
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,2);
			bodyDef.position.Set(7,2.5);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(9,5);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(17,5);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// create small movers
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.1);
			bodyDef.position.Set(4,15);
			bodyDef.userData="smallMover";
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(5, 0));
			temp.CreateFixture(fixDef);
			bodyDef.position.Set(8,11);
			temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(8, 0));
			temp.CreateFixture(fixDef);

			// create blitz movers
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(1,0.1);
			bodyDef.position.Set(4,14);
			bodyDef.userData="blitzMover";
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(10, 0));
			temp.CreateFixture(fixDef);
			bodyDef.position.Set(4,13);
			temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(12, 0));
			temp.CreateFixture(fixDef);
			bodyDef.position.Set(4,12);
			temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(9, 0));
			temp.CreateFixture(fixDef);
			bodyDef.position.Set(4,16);
			temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(17, 0));
			temp.CreateFixture(fixDef);

			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2+100);
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg1";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg2";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg3";
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			break;

			// level 7
			case 7:

			// create net at top
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,2);
			bodyDef.position.Set(13,2.5);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(11,5);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(2,0.3);
			bodyDef.position.Set(3,5);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// bouncing balls
			fixDef.shape = new b2CircleShape;
			fixDef.restitution = 1.5;
			bodyDef.type = b2_staticBody;

			bodyDef.position.Set(5,12.5);
			fixDef.shape.SetRadius(1.23);
			bodyDef.userData="bouncerLEFT";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(14,18);
			fixDef.shape.SetRadius(2.23);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData="bouncerRIGHT";
			bodyDef.position.Set(12,8);
			fixDef.shape.SetRadius(0.98);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData="bouncerDOWN";
			bodyDef.position.Set(6.3,4.8);
			fixDef.shape.SetRadius(0.62);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.restitution = 0.4;
			
			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2+100);
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg";
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			break;

			// level 8
			case 8:

			// create net at top
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(5,0.3);
			bodyDef.position.Set(11.5,5);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(0.3,1.8);
			bodyDef.position.Set(12.5,2.6);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(0.5,0.5);
			bodyDef.position.Set(5,1);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// Bouncy wall!
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.17,4);
			bodyDef.position.Set(0.7,7);
			bodyDef.userData="RIGHTSHOOTER";
			bodyDef.type = b2_kinematicBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(1.8,1.5);
			bodyDef.position.Set(4,16);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(3.2,0.9);
			bodyDef.position.Set(12,17);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(2,2);
			bodyDef.position.Set(17,11);
			bodyDef.userData="LEFTSHOOTER";
			bodyDef.type = b2_kinematicBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(0.5,1.2);
			bodyDef.position.Set(7,12);
			world.CreateBody(bodyDef).CreateFixture(fixDef);


			// Create an egg
 			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = 18;
			bodyDef.position.y = ptm(canvas_height);
			bodyDef.userData = "egg";
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			break;


			// level 9
			case 9:

			// create right-side net
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,12);
			bodyDef.position.Set(17,12);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// Maze stuff
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3.5,0.2);
			bodyDef.position.Set(8,9);
			bodyDef.userData="movnWall";
			bodyDef.type = b2_kinematicBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(5, 0));
			temp.CreateFixture(fixDef);

			fixDef.shape.SetAsBox(3.5,0.2);
			bodyDef.position.Set(4,12);
			temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(5, 0));
			temp.CreateFixture(fixDef);

			fixDef.shape.SetAsBox(3.5,0.2);
			bodyDef.position.Set(12,15);
			temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(5, 0));
			temp.CreateFixture(fixDef);


			fixDef.shape.SetAsBox(3.5,0.2);
			bodyDef.position.Set(5,18);
			temp = world.CreateBody(bodyDef);
			temp.SetLinearVelocity(new b2Vec2(5, 0));
			temp.CreateFixture(fixDef);

			// Cone at top stuff
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(3,0.3);
			bodyDef.position.Set(14,4);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			var temp = world.CreateBody(bodyDef);
			temp.SetPositionAndAngle(temp.GetWorldCenter(), rads(-50));
			temp.CreateFixture(fixDef);
			bodyDef.position.Set(6,4);
			var temp = world.CreateBody(bodyDef);
			temp.SetPositionAndAngle(temp.GetWorldCenter(), rads(50));
			temp.CreateFixture(fixDef);

			// BLAST BOMBS
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.7,0.7);
			bodyDef.position.Set(13,11.8);
			bodyDef.userData="blastr";
			bodyDef.type = b2_dynamicBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(6,14.8);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(10,8.8);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// Create an egg
 			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = ptm(canvas_width/2);
			bodyDef.position.y = ptm(canvas_height)-1.25;
			bodyDef.active = false;
			bodyDef.userData = "egg1";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg2";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg3";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg4";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg5";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.active = true;
			bodyDef.userData = "egg0";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			break;

			case 10:
			// walls at top
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.3,1.5);
			bodyDef.position.Set(7,1);
			bodyDef.userData="wall";
			bodyDef.type = b2_staticBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			fixDef.shape.SetAsBox(0.3,1.5);
			bodyDef.position.Set(13,1);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// random
			fixDef.shape = new b2CircleShape;
			bodyDef.type = b2_staticBody;
			bodyDef.userData="forcer";
			bodyDef.position.Set(5,12.5);
			fixDef.shape.SetRadius(1.23);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(12.1,3.9);
			fixDef.shape.SetRadius(1.23);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(12,16.2);
			fixDef.shape.SetRadius(1.23);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(4,7);
			fixDef.shape.SetRadius(1.23);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(15,10.5);
			fixDef.shape.SetRadius(1.23);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// WALLS
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.2,12);
			bodyDef.position.Set(19,ptm(canvas_height)/2);
			bodyDef.userData="LEFTSHOOTER";
			bodyDef.type = b2_kinematicBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(1,ptm(canvas_height)/2);
			bodyDef.userData="RIGHTSHOOTER";
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			// falling bombs
			fixDef.shape = new b2PolygonShape;
			fixDef.shape.SetAsBox(0.7,0.7);
			bodyDef.position.Set(13,11.8);
			bodyDef.userData="blastr";
			bodyDef.type = b2_dynamicBody;
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(6,14.8);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(10,8.8);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(12,10.2);
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.position.Set(11,12.8);
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			//create egg objects
			bodyDef.type = b2Body.b2_dynamicBody;
			fixDef.shape = new b2CircleShape(ptm(20));
			bodyDef.position.x = 12.4;
			bodyDef.position.y = ptm(canvas_height)-1.3;
			bodyDef.active = false;
			bodyDef.userData = "egg1";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg2";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg3";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.userData = "egg4";
			world.CreateBody(bodyDef).CreateFixture(fixDef);
			bodyDef.active = true;
			bodyDef.userData = "egg0";
			world.CreateBody(bodyDef).CreateFixture(fixDef);

			break;

			case 11:
			gameOver = true;



			default:
			break;
		}
	}

	function update() {
		world.Step(
               1 / 60   //frame-rate
            ,  10       //velocity iterations
            ,  10       //position iterations
            );
		if(won){
			if (!gameOver) {
				context.fillStyle = '#ffffff';
				context.font = '70px verdana';
				context.fillText("YOU WIN!", 120, 155);
				context.font = '50px verdana';
				context.fillText("Proceed to next level!", 25, 225);
			}
		}
		if(gameOver) {
			context.fillStyle = '#ffffff';
			context.font = '70px verdana';
			context.fillText("GAME", 180, 180);
			context.fillText("COMPLETED!", 80, 280)
			context.font = '40px verdana';
			context.fillText("Click 'Next Level' to", 100, 420);
			context.fillText("return to level 1", 125, 470);
		} else {
			if (!down) {
				for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
					if (bb.GetUserData()!=null) {
						if (bb.GetUserData().substr(0,3)=="egg") {
							var vel = bb.GetLinearVelocity();
							var velChange = -6 - vel.y;
							if (vel.y > 0) {velChange = -6;}
							var force = velChange/15.5;
							bb.ApplyForce(new b2Vec2(0, force), bb.GetWorldCenter());
							if (bb.GetPosition().x > 20) {
								world.DestroyBody(bb);
							} else if (bb.GetPosition().x < 0) {
								world.DestroyBody(bb);
							}
						}
					}
				}
			} else {
				world.ClearForces();
			}
			// Keep platforms moving.
			movePlatforms();
			// Draw the objects.
			world.DrawDebugData();
			// Redraw bunny (goal).	
			context.drawImage(goal, winningLocX, winningLocY);

			// See if there's a win!
			world.QueryAABB(checkBasket, winningArea);
		}
	};

// Converts meters to pixels
function mtp(meters)
{
	return meters * drawScale;
}

// Converts pixels to meters
function ptm(pixels)
{
	return pixels / drawScale;
}

// Rewrite level info box
function updateLevelInfo(idx) {
	levelSpec.textContent = levelDoc[idx];
}

// Reverses "gravity" on the egg when clicked and updates the displayed text.
gravityButton.onclick = function() {
	if (!won) {
		if (down) {
			gravityText.innerText = "DOWN";
		} else {
			gravityText.innerText = "UP";
		}
		down = !down;
	}
}

// Check to see if the egg has reached the bunny yet.
// Checks for a win.
function checkBasket(fixture){
	if (!won) {
		if (fixture.GetBody().GetUserData().substr(0,3)=="egg") {
			won = true;
			if (level==10) {
				gameOver = true;
			}
		}
	}
}

// When the next level button is clicked, clear the world and load next level.
nextLevelButton.onclick = function() 
{
	level = level + 1;
	
	if (gameOver) {
		level = 1;
		gameOver = false;
	}
	levelText.textContent = "Level " + level;
	if (level == 11) {
		gameOver = true;
		levelText.textContent = "fin";
	}

	clearWorld();
	loadLevel(level);
	updateLevelInfo(level);
}

// When the restart button is clicked, clear the world and restart the current level.
restartLevelButton.onclick = function() 
{
	clearWorld();
	loadLevel(level);
}

// Kill an egg by freezing it in place
function killEgg(idx)
{
	for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
		if (bb.GetUserData()!=null) {
			if (bb.GetUserData().substr(0,3)=="egg") {
				if (bb.GetUserData().substr(3)==idx) {
					bb.m_userData = "exploded";
					bb.SetActive(false);
				}
			}
		}
	}
}




// Clear the world (the bodies and forces in it).
function clearWorld()
{
	won = false;
	down = true;
	for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
		if (bb.GetUserData() != "ground") {
			world.DestroyBody(bb);
		}
	}
	for (var ff = world.m_fixtureList; ff; ff = ff.m_next) {
		world.DestoryFixture(ff);
	}
	for (var jj = world.m_jointList; jj; jj = jj.m_next) {
		world.DestoryJoint(jj);
	}
	world.ClearForces();
	gravityText.innerText = "UP";
}

// Convert degrees to radians.
function rads(degs)
{
	return degs * Math.PI/180;
}


// Controls how platforms in levels move and what their bounds are.
function movePlatforms() 
{
	if (level == 3) {
		for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
			if (bb.GetUserData() == "platform1") {
				if (bb.GetPosition().x > 17.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed1, 0));
				} else if (bb.GetPosition().x < 2.5) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
				}
			} else if (bb.GetUserData() == "platform2") {
				if (bb.GetPosition().x > 17.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed2, 0));
				} else if (bb.GetPosition().x < 2.5) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed2, 0));
				}
			}
		}
	} else if (level == 4) {
		for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
			if (bb.GetUserData() == "platform1") {
				if (bb.GetPosition().x > 13.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed1, 0));
				} else if (bb.GetPosition().x < 4.3) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
				}
			} else if (bb.GetUserData() == "platform2") {
				if (bb.GetPosition().x > 18.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed2, 0));
				} else if (bb.GetPosition().x < 11.3) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed2, 0));
				}
			} else 	if (bb.GetUserData() == "platform3") {
				if (bb.GetPosition().x > 17.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed3, 0));
				} else if (bb.GetPosition().x < 2.5) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed3, 0));
				}
			}
		}
	} else if (level == 5) {
		for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
			if (bb.GetUserData() == "smallPlatform") {
				if (bb.GetPosition().x > 18.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed1, 0));
				} else if (bb.GetPosition().x < 1.6) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
				}
			} else if (bb.GetUserData() == "bigPlatform") {
				if (bb.GetPosition().x > 16.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed2, 0));
				} else if (bb.GetPosition().x < 3.5) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed2, 0));
				}
			} else 	if (bb.GetUserData() == "catchPlatform") {
				if (bb.GetPosition().x > 17.5) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed3, 0));
				} else if (bb.GetPosition().x < 2.5) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed3, 0));
				}
			}
		}
	} else if (level==6) {
		for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
			if (bb.GetUserData() == "smallMover") {
				if (bb.GetPosition().x > 14) {
					bb.SetLinearVelocity(new b2Vec2(-platformSpeed1, 0));
				} else if (bb.GetPosition().x < 6) {
					bb.SetLinearVelocity(new b2Vec2(platformSpeed1, 0));
				}
			} else if (bb.GetUserData() == "blitzMover") {
				if (Math.abs(bb.GetLinearVelocity().x)>100) {
					bb.SetLinearVelocity(new b2Vec2(Math.abs(bb.GetLinearVelocity().x)-90, 0));
				}
				if (bb.GetPosition().x > 18.5) {
					bb.SetLinearVelocity(new b2Vec2(-(Math.abs(bb.GetLinearVelocity().x)+2), 0));
				} else if (bb.GetPosition().x < 2) {
					bb.SetLinearVelocity(new b2Vec2(Math.abs(bb.GetLinearVelocity().x)+2, 0));
				}
			}
		}
	} else if (level==9) {
		for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
			if (bb.GetUserData() == "movnWall") {
				if (bb.GetPosition().x > 12.5) {
					bb.SetLinearVelocity(new b2Vec2(-5,0));
				} else if (bb.GetPosition().x < 4.5) {
					bb.SetLinearVelocity(new b2Vec2(5,0));
				}
			} else if (bb.GetUserData() == "blastr") {
				var curVel = bb.GetLinearVelocity();
				bb.SetLinearVelocity(new b2Vec2(curVel.x, curVel.y*0.8));
				if (bb.GetPosition().y > 18) {
					bb.SetLinearVelocity(new b2Vec2(curVel.x+Math.random()), -1);
					bb.SetPosition(new b2Vec2((Math.random()*8)+4.5,10));
				}
			}
		}
	} else if (level==10) {
 		for (var bb = world.m_bodyList; bb; bb = bb.m_next) {
 			if (bb.GetUserData()!=null) {
 				if (bb.GetUserData()=="forcer") {
 				} else if (bb.GetUserData()=="blastr") {
 					var curVel = bb.GetLinearVelocity();
					bb.SetLinearVelocity(new b2Vec2(curVel.x, curVel.y*0.8));
					if (bb.GetPosition().y > 20) {
						bb.SetLinearVelocity(new b2Vec2(curVel.x+Math.random()), -1);
						bb.SetPosition(new b2Vec2((Math.random()*8)+4.5,8));
					}
 				}
 			}
 		}
	}
}

function SplashBeGone() {
  document.getElementById('splash').style.display = 'none';
}
